#!/usr/bin/python
# -*- coding: UTF-8 -*-

import os.path
import time
import calendar
import datetime
#import sys

from shutil import copyfile

#1MIN等于60s
MIN = 60
#获取数据间隔时间,单位：s,负载获取最小单位
sys_interval = 1*MIN
#统计数据片段时间,单位：s,负载统计最小单位
time_slice = 20*MIN
##数据存放文件
sys_percentage_file="/tmp/sys_percentage.db"

#-------------------------------------------------------------
#读写数据文件
class SysPercentageFile:

    def __init__(self):
        self.db = sys_percentage_file

    #写数据文件
    def Set(self,Value):
        with open(self.db,"w") as F:
            F.write(str(Value))
        F.close()
        return

    #读数据文件
    def Get(self):
        with open(self.db,"r") as F:
            tmp = ''.join(F.readlines())
        F.close()
        return eval( tmp )

    #检查数据文件是否已经存在
    def Check(self):
        return os.path.isfile(self.db) and os.path.getsize(self.db) > 0

#-------------------------------------------------------------
#当天日期
today = datetime.date.today()

def custom_time(startTime,endTime):
    customStart = time.mktime(startTime)
    customEnd = time.mktime(endTime)
    return customStart,customEnd

def get_daily():
    dayStart = int(time.mktime(today.timetuple())) #由今天日期，取得凌晨unix timestamp
    dayEnd = int(time.time()) #获取当前系统unix timestamp
    return dayStart,dayEnd
    #print dayStart,dayEnd

def get_weekly():
    lastMonday = today
    #取得上一个星期一
    while lastMonday.weekday() != calendar.MONDAY:
        lastMonday -= datetime.date.resolution
    
    weekStart = int(time.mktime(lastMonday.timetuple()))# 获取周一午夜的unix timestamp
    weekEnd = int(time.time())#获取当前系统unix timestamp
    weekofmonth = (today.day+7-1)/7
    return weekStart,weekEnd,weekofmonth
    #print weekStart,weekEnd,weekofmonth

def get_monthly():
    firstDay =  today #当前第一天的日期
    #取得当月第一天的日期
    while firstDay.day != 1:
        firstDay -= datetime.date.resolution
    monthStart = int(time.mktime(firstDay.timetuple())) #当月第一天的unix timestamp
    monthEnd = int(time.time())    #当前时间的unix timestamp
    return monthStart,monthEnd
    #print monthStart,monthEnd

#-------------------------------------------------------------
def get_mem_usage_percent():
    try:
        f = open('/proc/meminfo', 'r')
        for line in f:
            if line.startswith('MemTotal:'):
                mem_total = int(line.split()[1])
            elif line.startswith('MemFree:'):
                mem_free = int(line.split()[1])
            elif line.startswith('Buffers:'):
                mem_buffer = int(line.split()[1])
            elif line.startswith('Cached:'):
                mem_cache = int(line.split()[1])
            elif line.startswith('SwapTotal:'):
                vmem_total = int(line.split()[1])
            elif line.startswith('SwapFree:'):
                vmem_free = int(line.split()[1])
            else:
                continue
        f.close()
    except:
        return None
    physical_percent = usage_percent(mem_total - (mem_free + mem_buffer + mem_cache), mem_total)
    virtual_percent = 0
    if vmem_total > 0:
        virtual_percent = usage_percent((vmem_total - vmem_free), vmem_total)
    return physical_percent, virtual_percent

def usage_percent(use, total):
    try:
        ret = (float(use) / total) * 100
    except ZeroDivisionError:
        raise Exception("ERROR - zero division error")
    return ret

def get_cpu_time():
    need_sleep = False
    if not os.path.isfile('/tmp/cpu_stat') or os.path.getsize('/tmp/cpu_stat') == 0:
        copyfile('/proc/stat', '/tmp/cpu_stat')
        need_sleep = True

    try:
        try:
            f1 = open('/tmp/cpu_stat', 'r')
            first_line = f1.readline()
            if not first_line.startswith('cpu'):
                raise Exception('error cpu_stat content')
            values1 = first_line.split()
            total_time1 = 0
            for i in values1[1:]:
                total_time1 += int(i)
            idle_time1 = int(values1[4])
            iowait_time1 = int(values1[5])
        except Exception:
            copyfile('/proc/stat', '/tmp/cpu_stat')
            return None
    finally:
        f1.close()

    if need_sleep:
        time.sleep(1)

    f2 = open('/proc/stat', 'r')
    try:
        values2 = f2.readline().split()
        total_time2 = 0
        for i in values2[1:]:
            total_time2 += int(i)
        idle_time2 = int(values2[4])
        iowait_time2 = int(values2[5])
    finally:
        f2.close()
    idle_time = idle_time2 - idle_time1
    iowait_time = iowait_time2 - iowait_time1
    total_time = total_time2 - total_time1

    cpu_percentage = int(100.0 * (total_time - idle_time - iowait_time) / total_time)
    # compensate logic
    if total_time < 0 or idle_time < 0 or iowait_time < 0 or cpu_percentage < 0 or cpu_percentage > 100:
        time.sleep(1)
        f3 = open('/proc/stat', 'r')
        try:
            values3 = f3.readline().split()
            total_time3 = 0
            for i in values3[1:]:
                total_time3 += int(i)
            idle_time3 = int(values3[4])
            iowait_time3 = int(values3[5])
        finally:
            f3.close()
        idle_time = idle_time3 - idle_time2
        iowait_time = iowait_time3 - iowait_time2
        total_time = total_time3 - total_time2
        cpu_percentage = int(100.0 * (total_time - idle_time - iowait_time) / total_time)

    copyfile('/proc/stat', '/tmp/cpu_stat')
    return cpu_percentage

#时间点与对应的负载使用率信息
#    'sys_data':
#    {
#        'timestamp':[cpu,mem,swap]
#    }
def sys_statistic(sys_data):
    #__list : [__max,__avg,__min]
    cpu = []
    mem = []
    swap = []
    num = len(sys_data)
    #sta_statistic_list :[__max,__avg,__min],   ##cpu
    #                    [__max,__avg,__min],   ##mem
    #                    [__max,__avg,__min]    ##swap
    sta_statistic_list = []
    
    for _data in sys_data.values():
        #_data = [cpu,mem,swap]
        cpu.append(float(_data[0]))
        mem.append(float(_data[1]))
        swap.append(float(_data[2]))
    for x in cpu,mem,swap:
        _max = max(x)
        _avg = sum(x) / num
        _min = min(x)
        _list = [_max,_avg,_min]
        sta_statistic_list.append(_list)
    
    return sta_statistic_list

#-------------------------------------------------------------
#使用率数据收集
'''
    data:
    {
        #时间片最早一个时间戳
        'sys_start_time':
        #    timestamp
        #时间片最后一个时间戳
        'sys_end_time':
            timestamp + time_slice -1
        #时间片计算结果集:
          X 1、 (max,min,weight）
                weight：
                    1：10%,
                    2：20%,
                    3：50%,
                    4：80%,
                    5：90%
            2、 (max,avg,min)
        'sys_time':
        {
            'time_point':
            [
                [__max,__avg,__min],    #    cpu
                [__max,__avg,__min],    #    men
                [__max,__avg,__min],    #    swap
            ],
        }
        #时间点与对应的负载使用率信息
        'sys_data':
        {
            'timestamp':[cpu,mem,swap]
        }
    }
'''


def all_index():
    timestamp = int(time.time())
    cpu = get_cpu_time()
    mem = get_mem_usage_percent()
    
    memory_utilization = ''
    swap_utilization = ''
    cpu_utilization = ''

    if cpu is not None:
        cpu_utilization = cpu
    if mem is not None:
        memory_utilization = mem[0]
        swap_utilization = mem[1]

    sys_percentage = [cpu_utilization, memory_utilization,swap_utilization]
    return sys_percentage,timestamp

def collector():

    sys_percentage,timestamp = all_index()
    sys_percentage_file = SysPercentageFile()
    
    data = {}
    data['sys_data'] = {}
    data['sys_time'] = {}

    #判断是否已经生成数据文件
    #    有文件则获取其数据
    #    没有则生成时间片边界值
    if sys_percentage_file.Check():
        data = sys_percentage_file.Get()
    else:
        data['sys_start_time'] = timestamp
        data['sys_end_time'] = timestamp + time_slice - 1

    #判断数据是否在本时间片内：
    #    在此片断内就赋值
    #    等于边界值则开始计算此时间片内的各项统计值，生成下一个时间片边界值，并释放此时间片数据空间
    if timestamp <= data['sys_end_time']:
        data['sys_data'][str(timestamp)] = sys_percentage
    elif timestamp > data['sys_end_time']:
        #统计时间片内各项数据
        #    sys_type:1、求平均值 0、求比重
        statistic = sys_statistic(data['sys_data'])
        #print statistic
        
        #以sys_start_time作为时间点保存计算结果
        timepoint = data['sys_start_time']
        data['sys_time'][str(timepoint)] = statistic
        #清除废弃数据
        data['sys_data'] = {}
        
        #生成下一个时间片边界值
        data['sys_start_time'] = timestamp
        data['sys_end_time'] = timestamp + time_slice
        
        data['sys_data'][str(timestamp)] = sys_percentage

    #更新磁盘数据
    sys_percentage_file.Set(data)
    print len(data['sys_data'])
    print data
    #time.sleep(sys_interval)
collector()